#include "DeviceNode.h"
#include <QDebug>
#include <QMetaObject>
#include <QMutexLocker>
#include <algorithm>

DeviceNode::DeviceNode(const QString& deviceName, QObject* parent)
    : QObject(parent)
    , m_deviceName(deviceName)
{
    // 创建 CNPClient
    m_client = std::make_unique<CNPClient>(CNP_DOMAIN_ID(0), deviceName.toStdString());

    // 订阅状态（回调在 DDS 线程），回调尽量短：只入队并安排在对象线程处理
    CNP_RESULT r1 = m_client->subscribeStatus([
                                                  this](const CnpMsg& msg){
        QString content = QString::fromStdString(msg.content());
        {
            QMutexLocker locker(&m_statusMutex);
            if ((int)m_statusQueue.size() >= m_maxQueueSize) {
                // 丢弃最旧
                m_statusQueue.pop_front();
            }
            m_statusQueue.push_back(content);
            if (!m_statusScheduled) {
                m_statusScheduled = true;
                // 安排在 DeviceNode 所在线程处理队列（QueuedConnection）
                QMetaObject::invokeMethod(this, "processStatusQueue", Qt::QueuedConnection);
            }
        }
    }
                                              );
    if (r1 != CNP_RESULT::CNP_SUBSCRIBE_SUCCESS) {
        qWarning() << "DeviceNode" << deviceName << ": subscribeStatus failed";
    }

    // 订阅事件，同样处理
    CNP_RESULT r2 = m_client->subscribeEvent([
                                                 this](const CnpMsg& msg){
        QString content = QString::fromStdString(msg.content());
        {
            QMutexLocker locker(&m_eventMutex);
            if ((int)m_eventQueue.size() >= m_maxQueueSize) {
                m_eventQueue.pop_front();
            }
            m_eventQueue.push_back(content);
            if (!m_eventScheduled) {
                m_eventScheduled = true;
                QMetaObject::invokeMethod(this, "processEventQueue", Qt::QueuedConnection);
            }
        }
    }
                                             );
    if (r2 != CNP_RESULT::CNP_SUBSCRIBE_SUCCESS) {
        qWarning() << "DeviceNode" << deviceName << ": subscribeEvent failed";
    }
}

DeviceNode::~DeviceNode()
{
    // m_client 的析构应该释放 DDS 资源
}

void DeviceNode::publishCmd(const QString& deviceName,const QString& cmd)
{
    if (!m_client) return;
    CnpMsg msg;
    msg.device_id(deviceName.toStdString());
    auto now = std::chrono::system_clock::now();
    auto timestamp_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                            now.time_since_epoch()
                            ).count();
    msg.message_id(std::to_string(timestamp_ms));

    msg.content(cmd.toStdString());
    CNP_RESULT res = m_client->publishCmdRequest(msg);
    if (res != CNP_RESULT::CNP_PUBLISH_SUCCESS) {
        //qWarning() << "DeviceNode" << m_deviceName << ": publishCmd failed for" << cmd;
        qDebug() << "DeviceNode" << m_deviceName << ": publishCmd failed for" << cmd;
    }
    if (res == CNP_RESULT::CNP_PUBLISH_SUCCESS) {
        //std::cout << "Message " << msg.content() << " published successfully." << std::endl;
        qDebug() << "Message " << QString::fromStdString(msg.content()) << " published successfully." ;
    }
}


void DeviceNode::processStatusQueue()
{
    // 交换队列内容到本地，减少锁持有时间
    std::deque<QString> local;
    {
        QMutexLocker locker(&m_statusMutex);
        m_statusQueue.swap(local);
        m_statusScheduled = false;
    }

    // 只关心最新一条：如果队列非空，emit 最新消息并丢弃其他
    if (!local.empty()) {
        const QString &latest = local.back();
        emit cmdReceived(latest);
    }
}

void DeviceNode::processEventQueue()
{
    std::deque<QString> local;
    {
        QMutexLocker locker(&m_eventMutex);
        m_eventQueue.swap(local);
        m_eventScheduled = false;
    }

    for (const auto &s : local) {
        emit eventReceived(s);
    }
}
